using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Windows.Forms;
using System.Collections;
using System.ComponentModel;

using LowLevelGraphics.Filter;

namespace LowLevelGraphics
{
    /// <summary>
    /// These are the bitmap filters
    /// </summary>
	public class CBitmapFilter
    {
        #region Declarations
        #endregion Declarations

        #region Methods

        /// <summary>
        /// Draws the histogram.
        /// </summary>
        /// <param name="_aHistogram">The _a histogram.</param>
        /// <param name="_form">The _form.</param>
        public void DrawHistogram(int[] _aHistogram, PictureBox _form)
        {
            Bitmap bitmap = new Bitmap(_aHistogram.Length + 10, 310);
            _form.BackgroundImage = bitmap;
            //int keep = 0;

            BitmapData data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

            unsafe
            {
                int remain = data.Stride - data.Width * 3;
                byte* ptr = (byte*)data.Scan0;

                for (int i = 0; i < data.Height; i++)
                {
                    for (int j = 0; j < data.Width; j++)
                    {
                        ptr[0] = ptr[1] = ptr[2] = 150;
                        ptr += 3;
                    }
                    ptr += remain;
                }

                int nMax = 0;
                for (int i = 0; i < _aHistogram.Length; i++)
                {
                    if (nMax < _aHistogram[i])
                    {
                        nMax = _aHistogram[i];
                    }
                }

                for (int i = 0; i < _aHistogram.Length; i++)
                {
                    ptr = (byte*)data.Scan0;
                    ptr += data.Stride * (305) + (i + 5) * 3;

                    int length = (int)(1.0 * _aHistogram[i] * 300 / nMax);

                    for (int j = 0; j < length; j++)
                    {
                        ptr[0] = 255;
                        ptr[1] = ptr[2] = 0;
                        ptr -= data.Stride;
                    }

                }

            }
            bitmap.UnlockBits(data);
        }

        /// <summary>
        /// Equalizes the histogram.
        /// </summary>
        /// <param name="_bitmap">The _bitmap.</param>
        public void EqualizeHistogram(Bitmap _bitmap)
        {
            BitmapData data = _bitmap.LockBits(new Rectangle(0, 0, _bitmap.Width, _bitmap.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
            unsafe
            {
                byte* ptr = (byte*)data.Scan0;

                int remain = data.Stride - data.Width * 3;

                int[] aHistogram = new int[256];
                for (int i = 0; i < aHistogram.Length; i++)
                    aHistogram[i] = 0;

                for (int i = 0; i < data.Height; i++)
                {
                    for (int j = 0; j < data.Width; j++)
                    {
                        int mean = ptr[0] + ptr[1] + ptr[2];
                        mean /= 3;

                        aHistogram[mean]++;
                        ptr += 3;
                    }
                    ptr += remain;
                }

                float[] LUT = Equalize(aHistogram, data.Width * data.Height);
                ptr = (byte*)data.Scan0;

                for (int i = 0; i < data.Height; i++)
                {
                    for (int j = 0; j < data.Width; j++)
                    {
                        int index = ptr[0];
                        byte nValue = (byte)LUT[index];
                        if (LUT[index] > 255)
                            nValue = 255;
                        ptr[0] = ptr[1] = ptr[2] = nValue;
                        ptr += 3;
                    }
                    ptr += remain;
                }

                ptr = (byte*)data.Scan0;

                aHistogram = new int[256];
                for (int i = 0; i < aHistogram.Length; i++)
                {
                    aHistogram[i] = 0;
                }

                for (int i = 0; i < data.Height; i++)
                {
                    for (int j = 0; j < data.Width; j++)
                    {
                        int mean = ptr[0];

                        aHistogram[mean]++;
                        ptr += 3;
                    }

                    ptr += remain;
                }
                //drawHistogram(histogram, form);
            }

            _bitmap.UnlockBits(data);
        }

        /// <summary>
        /// Equalizes the specified _a histogram.
        /// </summary>
        /// <param name="_aHistogram">The _a histogram.</param>
        /// <param name="_numPixel">The _num pixel.</param>
        /// <returns></returns>
        public float[] Equalize(int[] _aHistogram, long _numPixel)
        {
            float[] aHist = new float[256];

            aHist[0] = _aHistogram[0] * _aHistogram.Length / _numPixel;
            long lPrev = _aHistogram[0];
            string sString = "";
            sString += (int)aHist[0] + "\n";

            for (int i = 1; i < aHist.Length; i++)
            {
                lPrev += _aHistogram[i];
                aHist[i] = lPrev * _aHistogram.Length / _numPixel;
                sString += (int)aHist[i] + "   _" + i + "\t";
            }

            //	MessageBox.Show( str );
            return aHist;
        } 	  
        #endregion Methods
    }
}
